package com.dingding.web.base.action;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;

import com.dingding.common.core.base.dto.FacadeResult;
import com.dingding.common.core.util.JSONUtil;
import com.dingding.common.core.util.ToolUtil;
import com.dingding.facade.mall.service.IUserMallFacade;
import com.dingding.facade.mall.status.StatusCode;
import com.dingding.facde.activity.enums.ActivityEnum.CouponStatus;
import com.dingding.facde.activity.service.IActivityFacade;
import com.dingding.facde.common.IPhonevalidateService;
import com.dingding.facde.coupon.ICouponService;
import com.dingding.facde.coupon.IStoreManagerService;
import com.dingding.facde.coupon.dto.ResponseDataDTO;
import com.dingding.facde.coupon.dto.WechatValidation;
import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class BaseAction extends ActionSupport {

	protected Logger log = Logger.getLogger(BaseAction.class);
	protected HttpServletRequest request = ServletActionContext.getRequest();
	protected HttpServletResponse response = ServletActionContext.getResponse();

	@Resource(name = "userMallFacade")
	protected IUserMallFacade userMallFacade; // 用户商城业务接口

	// 微信js-sdk验证bean
	protected WechatValidation validation;

	// 门店管理员service
	@Resource(name = "storeManagerService")
	protected IStoreManagerService storeManagerService;

	// 优惠券service
	@Resource(name = "couponService")
	protected ICouponService couponService;

	// 验证码Service
	@Resource(name = "phonevalidateService")
	protected IPhonevalidateService phonevalidateService;
	
	@Resource(name = "activityFacade")
	private IActivityFacade activityFacade;

	/**
	 * @Title: write @Description: 输出数据到response @return boolean true 成功
	 *         false：失败 @author cheshaowei @throws
	 */
	protected void write(String text) {
		try {
			ServletActionContext.getResponse().setCharacterEncoding("utf-8");
			ServletActionContext.getResponse().getWriter().write(text);
			ServletActionContext.getResponse().getWriter().close();
		} catch (IOException e) {
			log.error("输出数据出现错误！BaseAction：write()", e);
		}
	}

	/**
	 * @Description: 返回前台jsonp跨域json数据
	 * @author fengshuonan
	 * @return void
	 */
	protected void writeResponseJsonp(Object obj) {
		this.write(this.getResJsonp(obj));
	}

	/**
	 * @Description:返回前台jsonp跨域json数据
	 * @author fengshuonan
	 * @since 2.3.0
	 */
	protected void writeResponseJsonp(int code, String message, Object obj) {
		this.write(this.generateResponseData(code, message, obj));
	}

	/**
	 * @Description:返回前台jsonp跨域json数据
	 * @author fengshuonan
	 * @since 2.3.0
	 */
	protected void writeResponseJsonp(int code, String message) {
		this.write(this.generateResponseData(code, message, null));
	}

	/**
	 * @Description:把响应bean封装为jsonp格式
	 * @param obj
	 *            被封装的bean
	 * @author fengshuonan
	 * @return String
	 */
	protected String getResJsonp(Object obj) {
		if (obj instanceof List) {
			if (obj == null || ((List) obj).size() <= 0) {
				return generateResponseData(StatusCode.NULL_PARA, null);
			}
		}

		if (obj == null) {
			return generateResponseData(StatusCode.NULL_PARA, obj);
		} else {
			return generateResponseData(StatusCode.SUCCESS, obj);
		}
	}

	/**
	 * @Description:把响应bean封装为jsonp格式
	 * @param obj
	 *            被封装的bean
	 * @author fengshuonan
	 * @return String
	 */
	protected String getResJsonp(Object obj, String format) {
		if (obj instanceof List) {
			if (obj == null || ((List) obj).size() <= 0) {
				return generateResponseData(StatusCode.NULL_PARA, null);
			}
		}

		if (obj == null) {
			return generateResponseData(StatusCode.NULL_PARA, obj);
		} else {
			return responseData(StatusCode.SUCCESS, obj, format);
		}
	}

	/**
	 * @Description: 封装跨域json数据
	 * @param code
	 *            状态码
	 * @param errorMessage
	 *            错误信息
	 * @param obj
	 *            被封装的bean的对象
	 * @author fengshuonan
	 * @return String jsonp字符串
	 */
	protected String generateResponseData(int code, Object obj) {

		ResponseDataDTO responseDataDTO = new ResponseDataDTO();

		responseDataDTO.setCode(code);

		StatusCode statusCode = new StatusCode();
		Field[] fields = statusCode.getClass().getFields();
		try {
			for (Field f : fields) {
				if (f.get(statusCode) instanceof Integer) {
					if ((Integer) f.get(statusCode) == code) {
						Field field = statusCode.getClass().getField(f.getName() + "_MESSAGE");
						String msg = (String) field.get(statusCode);
						responseDataDTO.setErrorMessage(msg);
					}
				}
			}
		} catch (Exception e) {
			log.error("获取错误信息出错！BaseAction：generateResponseData（）", e);
		}

		if (obj != null) {
			responseDataDTO.setResponseBody(obj);
		}

		String resJson = JSONUtil.toJSONString(responseDataDTO, "yyyy年MM月dd日");

		// 跨域（jsonp）传输必须加callback
		String callback = getPara("callback");
		resJson = callback + "(" + resJson + ")";

		return resJson;
	}

	/**
	 * @Description: 封装跨域json数据
	 * @param code
	 *            状态码
	 * @param errorMessage
	 *            错误信息
	 * @param obj
	 *            被封装的bean的对象
	 * @author fengshuonan
	 * @return String jsonp字符串
	 */
	protected String responseData(int code, Object obj, String format) {

		ResponseDataDTO responseDataDTO = new ResponseDataDTO();

		responseDataDTO.setCode(code);

		StatusCode statusCode = new StatusCode();
		Field[] fields = statusCode.getClass().getFields();
		try {
			for (Field f : fields) {
				if (f.get(statusCode) instanceof Integer) {
					if ((Integer) f.get(statusCode) == code) {
						Field field = statusCode.getClass().getField(f.getName() + "_MESSAGE");
						String msg = (String) field.get(statusCode);
						responseDataDTO.setErrorMessage(msg);
					}
				}
			}
		} catch (Exception e) {
			log.error("获取错误信息出错！BaseAction：generateResponseData（）", e);
		}

		if (obj != null) {
			responseDataDTO.setResponseBody(obj);
		}

		String resJson = JSONUtil.toJSONString(responseDataDTO, format);

		// 跨域（jsonp）传输必须加callback
		String callback = getPara("callback");
		resJson = callback + "(" + resJson + ")";

		return resJson;
	}

	/**
	 * @Description: 封装返回前台的json数据
	 * @param code
	 *            状态码
	 * @param errorMessage
	 *            错误信息
	 * @param obj
	 *            被封装的bean的对象
	 * @author fengshuonan
	 */
	protected String generateResponseData(int code, String errorMessage, Object obj) {

		ResponseDataDTO responseDataDTO = new ResponseDataDTO();
		responseDataDTO.setCode(code);
		responseDataDTO.setErrorMessage(errorMessage);
		responseDataDTO.setResponseBody(obj);

		String resJson = JSONUtil.toJSONString(responseDataDTO, "yyyy年MM月dd日");
		// 跨域（jsonp）传输必须加callback
		String callback = getPara("callback");
		resJson = callback + "(" + resJson + ")";

		return resJson;
	}

	/**
	 * @Description:返回给前台空请求参数异常
	 * @author fengshuonan
	 * @since 2.4
	 */
	protected void writeNullParaError() {
		this.write(this.generateResponseData(400, "请求参数异常", null));
	}

	/**
	 * @Description: 验证网页是否重复刷新
	 * @author fengshuonan
	 * @return boolean true 是重复的 false 不是重复的
	 */
	protected boolean validateRefresh() {
		Cookie[] cooks = ServletActionContext.getRequest().getCookies();

		if (cooks != null) {
			for (Cookie cook : cooks) {
				if ("validate".equals(cook.getName())) {
					return true;
				}
			}
		} else {
			Cookie cook = new Cookie("validate", "true");
			cook.setMaxAge(60 * 60 * 24);// 期限一天
			ServletActionContext.getResponse().addCookie(cook);
		}

		return false;
	}

	/**
	 * @Description: 获取网页传值
	 * @param par
	 *            传值字段
	 * @author fengshuonan
	 * @return String 对应字段的值
	 */
	protected String getPara(String par) {
		return ServletActionContext.getRequest().getParameter(par);
	}

	/**
	 * @Description: 设置网页传值
	 * @param key
	 *            传值的字段名
	 * @param val
	 *            对应字段的值
	 * @author fengshuonan
	 * @return void
	 */
	protected void setPara(String key, String val) {
		ServletActionContext.getRequest().setAttribute(key, val);
	}

	public IUserMallFacade getUserMallFacade() {
		return userMallFacade;
	}

	public void setUserMallFacade(IUserMallFacade userMallFacade) {
		this.userMallFacade = userMallFacade;
	}

	/**
	 * @Title: getWechatValidation @Description: 获取微信js-sdk接入验证,并封装 @author
	 *         fengshuonan @return WechatValidation @throws
	 */
	public static WechatValidation getWechatValidation(HttpServletRequest request) {
		String url = request.getRequestURL() + (request.getQueryString() == null ? "" : "?" + request.getQueryString());
		String nonceStr = ToolUtil.getRandString(16);
		String timestamp = String.valueOf(System.currentTimeMillis());
		String signature = ToolUtil.getSignature(nonceStr, timestamp, url);

		WechatValidation validation = new WechatValidation();
		validation.setNonceStr(nonceStr);
		validation.setSignature(signature);
		validation.setTimestamp(timestamp);
		return validation;
	}

	/**
	 * @Description:返回给前台facade调用结果
	 * @author fengshuonan
	 * @since 2.4
	 */
	protected void writeFacade(FacadeResult<?> facade) {
		String jsonString = this.generateResponseData(facade.getCode(), facade.getMessage(), facade.getObject());

		this.write(jsonString);
	}

	protected String forward(String url) {
		try {
			request.getRequestDispatcher(url).forward(request, response);
			return NONE;
		} catch (ServletException e) {
			e.printStackTrace();
			return ERROR;
		} catch (IOException e) {
			e.printStackTrace();
			return ERROR;
		}
	}

	protected String redirect(String url) {
		try {
			response.sendRedirect(url);
			return NONE;
		} catch (IOException e) {
			e.printStackTrace();
			return ERROR;
		}
	}

	protected String getSessionGraphCode() {
		Object sessionobj = request.getSession().getAttribute(request.getSession().getId());
		if (sessionobj == null) {
			return "";
		} else {
			return sessionobj.toString().toLowerCase();
		}
	}

	/**
	 * @Description:存用户的id到session
	 * @author fengshuonan
	 * @since 2.4
	 */
	protected void setSessionUserId(String userId) {
		request.getSession().setAttribute("weChatUserId", userId);
	}

	/**
	 * @Description:获取session中的用户的id
	 * @author fengshuonan
	 * @since 2.4
	 */
	protected String getSessionUserId() {
		Object obj = request.getSession().getAttribute("weChatUserId");
		if (obj == null) {
			return null;
		} else {
			return obj.toString();
		}
	}

	/**
	 * @Description 参加活动
	 * @author fengshuonan
	 * @return int (2:领取成功 5：异常或者领取失败)
	 */
	protected int joinActivity(String userId) {

		HashMap<String, Object> hashMap = new HashMap<String, Object>();
		hashMap.put("userId", userId);

		try {
			Map<String, Object> joinActivity = this.activityFacade.joinActivity(hashMap);

			// 判断接口调用是否成功
			boolean dubboFlag = (boolean) joinActivity.get("resStatus");
			if (dubboFlag == true) {

				// 判断是否领取成功
				boolean isReceiveCoupon = (boolean) joinActivity.get("grantCouponStatus");

				if (isReceiveCoupon == true) {
					return 2;
				} else {
					return 5;
				}

			} else {
				throw new RuntimeException("dubbo调用返回状态码错误！resStatus = " + dubboFlag + ",map = " + joinActivity);
			}
		} catch (Exception e) {
			log.error("调用dubbo出现 异常！", e);
			return 5;
		}
	}

	/**
	 * @Description 判断一个用户是否领取过优惠券
	 * @author fengshuonan
	 * @return int (3:已经领取过优惠券 2：没有领取过优惠券 5：异常)
	 */
	protected int judgeUserIsGotCoupon(String activityId, String userId) {
		// 判断5000张优惠券是否领完(结束包括日期期限到了，还有优惠券领取完)
		HashMap<String, Object> hashMap = new HashMap<String, Object>();
		hashMap.put("activityId", activityId);
		hashMap.put("userId", userId);

		try {
			Map<String, Object> result = this.activityFacade.isReceiveCoupon(hashMap);

			// 判断接口调用是否成功
			boolean dubboFlag = (boolean) result.get("resStatus");
			if (dubboFlag == true) {

				// 是否领取过优惠券
				boolean isReceiveCoupon = (boolean) result.get("isReceiveCoupon");
				if (isReceiveCoupon == true) {
					return 3;
				} else {
					return 2;
				}

			} else {
				throw new RuntimeException("dubbo调用返回状态码错误！resStatus = " + dubboFlag + ",map = " + result);
			}
		} catch (Exception e) {
			log.error("调用dubbo出现 异常！", e);
			return 5;
		}

	}

	/**
	 * @Description 判断活动是否结束，如果结束跳转到相应界面，如果没结束返回null
	 * @return 1:优惠券领取完毕 4：活动到期 0：活动还在进行 5:异常
	 * @author fengshuonan
	 */
	protected int judgeActivityFinish(String activityId) {
		try {
			// 判断5000张优惠券是否领完(结束包括日期期限到了，还有优惠券领取完)
			HashMap<String, Object> hashMap = new HashMap<String, Object>();
			hashMap.put("activityId", activityId);

			// 调用dubbo接口，获取是否活动截止日期到了，是否优惠券领取完毕
			Map<String, Object> grantCouponComplete = this.activityFacade.isGrantCouponComplete(hashMap);

			// 判断接口调用是否成功
			boolean dubboFlag = (boolean) grantCouponComplete.get("resStatus");
			if (dubboFlag == true) {
				CouponStatus couponStatus = (CouponStatus) grantCouponComplete.get("isGrantComplete");

				// 如果优惠券领完，跳转至优惠券领取完界面
				if (couponStatus == CouponStatus.couponGrantComplet) {
					return 1;

					// 如果活动到期，跳转到活动到期界面
				} else if (couponStatus == CouponStatus.couponInvalid) {
					return 4;

					// 标示活动没结束
				} else if (couponStatus == CouponStatus.couponEffective) {
					return 0;

					// 活动异常
				} else {
					return 5;
				}
			} else {
				throw new RuntimeException("dubbo调用返回状态码错误！resStatus = " + dubboFlag + ",map = " + grantCouponComplete);
			}
		} catch (Exception e) {
			log.error("调用dubbo出现 异常！", e);
			return 5;
		}
	}

}
